from machine import Pin, I2C
import ssd1306
import settings as st
import time

class UI():
    MENU_OFFSET = 4
    MENU_MAX = 4
    MSG_MARGIN = 4
    MSG_HEIGHT = int(st.OLED_HEIGHT / 3 * 2)
    MSG_WIDTH = st.OLED_WIDTH
    MSG_TOP = int((st.OLED_HEIGHT - MSG_HEIGHT) / 2)
    
    LIGHTNING_CENTER = int(st.OLED_WIDTH - 2 - (st.BATTERY_WIDTH / 2))
    def __init__(self):
        i2c = I2C(-1, scl=Pin(st.I2C_SCL), sda=Pin(st.I2C_SDA))
        self.oled = ssd1306.SSD1306_I2C(st.OLED_WIDTH, st.OLED_HEIGHT, i2c) #, addr=0x3d, external_vcc=True
        self.init()
    
    def init(self):
        self.menu_select = 0
        self.menu_index = 0
        self.menu_dir = False # False: down, True: up
        self.menu = []
        self.current = {
            "status_bar": "",
            "main_content": "",
        }
        self.draw_top()

    def draw_menu(self):
        self.current["main_content"] = self.draw_menu
        if self.menu_dir:
            offset = 2
        else:
            offset = 1
        start = max(0, self.menu_index - offset)
        start = min(len(self.menu) - self.MENU_MAX, start)
        end = start + self.MENU_MAX
        
        new_menu = self.menu[start:end]
        self.oled.fill_rect(0, 12, 128, 52, 0)
        for i in range(self.MENU_MAX):
        #for i, item in enumerate(self.menu):
            select_index = i + start
            item = self.menu[select_index]
            if self.menu_index == select_index:
                self.oled.fill_rect(0, 12*(i+1) + self.MENU_OFFSET - 2, 128, 12, 1)
                self.oled.text(item[0], 0, 12*(i+1) + self.MENU_OFFSET, 0)
            else:
                self.oled.text(item[0], 0, 12*(i+1) + self.MENU_OFFSET)
        
    def draw_top(self):
        self.current["status_bar"] = self.draw_top
        self.oled.text('ESP Remote', 0, 0)
        self.oled.rect(128-st.BATTERY_WIDTH-2, 0, st.BATTERY_WIDTH, st.BATTERY_HEIGHT, 1)
        self.oled.rect(128-3, int(st.BATTERY_HEIGHT/4), 3, int(st.BATTERY_HEIGHT/2), 1)
        self.oled.hline(0, 10, 128, 1)

    def draw_battery_charging(self):
        self.oled.fill_rect(128-st.BATTERY_WIDTH-2+2, 2, st.BATTERY_WIDTH - 4, st.BATTERY_HEIGHT-4, 1)
        self.oled.line(self.LIGHTNING_CENTER + 1, 2, self.LIGHTNING_CENTER - 1, 4, 0)
        self.oled.line(self.LIGHTNING_CENTER - 1, 4, self.LIGHTNING_CENTER + 1, 4, 0)
        self.oled.line(self.LIGHTNING_CENTER + 1, 4, self.LIGHTNING_CENTER - 1, 6, 0)

    def draw_battery_level(self, val):
        width = int((st.BATTERY_WIDTH - 4) * val / 100)
        self.oled.fill_rect(128-st.BATTERY_WIDTH-2+2, 2, st.BATTERY_WIDTH - 4, st.BATTERY_HEIGHT-4, 0)
        self.oled.fill_rect(128-st.BATTERY_WIDTH-2+2, 2, width, st.BATTERY_HEIGHT-4, 1)

    def show_msg(self, *msg, timeout = 1):
        self.oled.fill_rect(0, self.MSG_TOP, self.MSG_WIDTH, self.MSG_HEIGHT, 0)
        self.oled.hline(0, self.MSG_TOP+self.MSG_MARGIN, self.MSG_WIDTH, 1)
        self.oled.hline(0, self.MSG_TOP+self.MSG_HEIGHT-self.MSG_MARGIN, self.MSG_WIDTH, 1)
        if len(msg) == 1:
            self.oled.text(msg[0], 4, int(st.OLED_HEIGHT/2) - 4)
        elif len(msg) == 2:
            x1 = int((st.OLED_WIDTH - (len(msg[0]) * 7)) / 2)
            x2 = int((st.OLED_WIDTH - (len(msg[1]) * 7)) / 2)
            self.oled.text(msg[0], x1, int(st.OLED_HEIGHT/2) - 9)
            self.oled.text(msg[1], x2, int(st.OLED_HEIGHT/2) + 1)
        else:
            raise ValueError("msg must have 1 or 2 lines")
        self.show()
        time.sleep(timeout)
        self.hide_msg()
    
    def hide_msg(self):
        for content in self.current:
            self.current[content]()
        self.show()
        
    def menu_next(self):
        #self.menu_select = min(self.MENU_MAX, self.menu_select + 1)
        self.menu_index = min(len(self.menu) - 1, self.menu_index + 1)
        print(self.menu_index)
        self.draw_menu()

    def menu_prev(self):
        #self.menu_select = max(0, self.menu_select - 1)
        self.menu_index = max(0, self.menu_index - 1)
        print(self.menu_index)
        self.draw_menu()

    def show(self):
        self.oled.show()
    
    def close(self):
        self.oled.poweroff()